//
// Created by PulsarV on 18-10-30.
//

#ifndef ROBOCAR_RC_BASE_MSG_H
#define ROBOCAR_RC_BASE_MSG_H

#include <queue>
#include <list>
#include <map>
#include <mutex>

namespace rccore {
    namespace message {
        template<typename T>
        class BaseMessage {
        public:
            std::list<T> self_message_queue;
            T self_message_data;
            int max_queue_size;
            std::mutex message_mutex;
        public:
            BaseMessage(int max_queue_size) {
                if (max_queue_size <= 0)
                    this->max_queue_size = 1;
            };


            virtual void push_message(T cell) {
                std::unique_lock<std::mutex> message_mutex_lock(message_mutex);
                if (max_queue_size > 1) {
                    self_message_queue.push_back(cell);
                    if ((int) self_message_queue.size() > max_queue_size)
                        _pop_message();
                } else {
                    self_message_data = cell;
                }
                message_mutex_lock.unlock();
            }

            virtual T front_message() {
                std::unique_lock<std::mutex> message_mutex_lock(message_mutex);
                if (max_queue_size > 1) {
                    T data = self_message_queue.front();
                    message_mutex_lock.unlock();
                    return data;
                } else {
                    T data = self_message_data;
                    message_mutex_lock.unlock();
                    return data;
                }
            }

            bool empty() {
                if (max_queue_size > 1) {
                    return self_message_queue.empty();
                } else {
                    return false;
                }

            }

            virtual T back_message() {
                std::unique_lock<std::mutex> message_mutex_lock(message_mutex);
                if (max_queue_size > 1) {
                    T data = self_message_queue.back();
                    message_mutex_lock.unlock();
                    return data;
                } else {
                    T data = self_message_data;
                    message_mutex_lock.unlock();
                }
            }

            int size_message() {
                return self_message_queue.size();
            }

            void release_message() {
                std::unique_lock<std::mutex> message_mutex_lock(message_mutex);
                self_message_queue.clear();
                message_mutex_lock.unlock();
            }

            void pop_message() {
                std::unique_lock<std::mutex> message_mutex_lock(message_mutex);
                _pop_message();
                message_mutex_lock.unlock();
            }

        protected:
            void _pop_message() {
                if (not self_message_queue.empty())
                    self_message_queue.pop_front();
            }
        };
    }
}
#endif //ROBOCAR_RC_BASE_MSG_H
